package com.epam.service.serviceImpl;

import com.epam.Entity.*;
import com.epam.Model.CreateOrderModel;
import com.epam.Model.OrderItemModel;
import com.epam.Model.OrderResponseModel;
import com.epam.repository.*;
import com.epam.service.OrderService;
import org.assertj.core.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Transactional
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private VipRepository vipRepository;

    @Autowired
    private OrderItemRepository orderItemRepository;

    @Autowired
    private BookRepository bookRepository;

    @Autowired
    private UserRepository userRepository;

    @Override
    public OrderResponseModel createOrder(CreateOrderModel order) {
        Order orderSave = new Order();
        //use h2DB need to set id
        String orderId = UUID.randomUUID().toString();
        orderSave.setOrderId(orderId);
        orderSave.setUserId(order.getUserId());
        orderSave.setCreateTime(DateUtil.now());
        orderSave.setModifyTime(DateUtil.now());
        //save order
        Order res = orderRepository.saveAndFlush(orderSave);
        System.out.print(res);
        List<OrderItem> list = order.getOrderItemList();
        List<String> bookIds = new ArrayList<>();
        List<Book> bookList = new ArrayList<>();
        list.forEach(item -> {
            item.setItemId(UUID.randomUUID().toString());
            item.setOrderId(orderId);
            bookIds.add(item.getBookId());
            bookList.add(bookRepository.getBookByBookId(item.getBookId()));
        });
        orderItemRepository.saveAll(list);
        Map<String, Book> map = bookList.stream().collect(Collectors.toMap(Book::getBookId, Function.identity(), (key1, key2) -> key2));
        Integer totalPrice = 0;
        for (OrderItem item : list) {
            totalPrice += item.getCount() * map.get(item.getBookId()).getBookPrice();
        }
        //update the user point
        User user = userRepository.getUserByUserId(order.getUserId());
        Integer beforePoints = Optional.of(user).filter(p->p.getVipPoints()!=null).map(p->p.getVipPoints()).orElse(0);
        //get vip rule
        VipRule vipRule = vipRepository.getVipRuleByVipType(user.getVipType());
        user.setVipPoints(beforePoints + totalPrice * vipRule.getPointsRule());
        user.setModifyTime(DateUtil.now());
        userRepository.saveAndFlush(user);
        return this.searchOrder(orderId);
    }

    @Override
    public OrderResponseModel searchOrder(String orderId) {
        OrderResponseModel result = new OrderResponseModel();
        if (orderId != null) {
            Order res = orderRepository.findById(orderId).get();
            result.setOrderId(res.getOrderId());
            result.setUserId(res.getUserId());
            result.setCreateTime(res.getCreateTime());
            result.setModifyTime(res.getModifyTime());
            List<OrderItem> list = orderItemRepository.findAllByOrderId(orderId);
            List<OrderItemModel> orderItemList = new ArrayList<>();
            list.forEach(item -> {
                OrderItemModel orderItemModel = new OrderItemModel();
                Book book = bookRepository.getBookByBookId(item.getBookId());
                orderItemModel.setBookId(item.getBookId());
                orderItemModel.setBookName(book.getBookName());
                orderItemModel.setBookPrice(book.getBookPrice());
                orderItemModel.setCount(item.getCount());
                orderItemModel.setOrderId(item.getOrderId());
                orderItemModel.setItemId(item.getItemId());
                orderItemList.add(orderItemModel);
            });
            result.setOrderItemList(orderItemList);
        }
        return result;
    }

}
